শুরু থেকে FastAPI মিডলওয়্যার আয়ত্ত করুন। এই নির্দেশিকাটি কাস্টম মিডলওয়্যার, প্রমাণীকরণ, লগিং, এবং শক্তিশালী API তৈরির সেরা অনুশীলনগুলি নিয়ে আলোচনা করে।
পাইথন FastAPI মিডলওয়্যার: রিকোয়েস্ট এবং রেসপন্স প্রসেসিং-এর একটি বিস্তারিত গাইড
আধুনিক ওয়েব ডেভেলপমেন্টের জগতে পারফরম্যান্স, নিরাপত্তা এবং রক্ষণাবেক্ষণযোগ্যতা সবচেয়ে গুরুত্বপূর্ণ। পাইথনের FastAPI ফ্রেমওয়ার্কটি তার অবিশ্বাস্য গতি এবং ডেভেলপার-বান্ধব বৈশিষ্ট্যের জন্য দ্রুত জনপ্রিয়তা অর্জন করেছে। এর সবচেয়ে শক্তিশালী অথচ কখনও কখনও ভুল বোঝা বৈশিষ্ট্যগুলির মধ্যে একটি হলো মিডলওয়্যার। মিডলওয়্যার রিকোয়েস্ট এবং রেসপন্স প্রসেসিং চেইনে একটি গুরুত্বপূর্ণ লিঙ্ক হিসাবে কাজ করে, যা ডেভেলপারদেরকে একটি রিকোয়েস্ট তার গন্তব্যে পৌঁছানোর আগে বা ক্লায়েন্টের কাছে একটি রেসপন্স পাঠানোর আগে কোড চালানো, ডেটা পরিবর্তন করা এবং নিয়ম প্রয়োগ করার অনুমতি দেয়।
এই বিস্তারিত নির্দেশিকাটি বিশ্বব্যাপী ডেভেলপারদের জন্য ডিজাইন করা হয়েছে, যারা সবেমাত্র FastAPI শুরু করেছেন তাদের থেকে শুরু করে অভিজ্ঞ পেশাদার যারা তাদের জ্ঞানকে আরও গভীর করতে চান। আমরা মিডলওয়্যারের মূল ধারণাগুলি অন্বেষণ করব, কীভাবে কাস্টম সমাধান তৈরি করতে হয় তা দেখাব এবং বাস্তব জগতের ব্যবহারিক উদাহরণগুলি আলোচনা করব। এটি শেষ করার পর, আপনি আরও শক্তিশালী, নিরাপদ এবং দক্ষ API তৈরি করতে মিডলওয়্যার ব্যবহার করার জন্য প্রস্তুত হবেন।
ওয়েব ফ্রেমওয়ার্কের প্রেক্ষাপটে মিডলওয়্যার কী?
কোডে যাওয়ার আগে, ধারণাটি বোঝা অপরিহার্য। আপনার অ্যাপ্লিকেশনের রিকোয়েস্ট-রেসপন্স চক্রটিকে একটি পাইপলাইন বা একটি অ্যাসেম্বলি লাইন হিসাবে কল্পনা করুন। যখন একজন ক্লায়েন্ট আপনার API-তে একটি রিকোয়েস্ট পাঠায়, তখন এটি সরাসরি আপনার এন্ডপয়েন্ট লজিকে আঘাত করে না। পরিবর্তে, এটি একাধিক প্রসেসিং ধাপের মধ্য দিয়ে যায়। একইভাবে, যখন আপনার এন্ডপয়েন্ট একটি রেসপন্স তৈরি করে, তখন এটি ক্লায়েন্টের কাছে পৌঁছানোর আগে এই ধাপগুলির মধ্য দিয়ে ফিরে আসে। মিডলওয়্যার উপাদানগুলি হলো এই পাইপলাইনের ধাপগুলি।
একটি জনপ্রিয় উপমা হলো পেঁয়াজের মডেল। পেঁয়াজের কেন্দ্র হলো আপনার অ্যাপ্লিকেশনের বিজনেস লজিক (এন্ডপয়েন্ট)। কেন্দ্রের চারপাশে পেঁয়াজের প্রতিটি স্তর হলো এক একটি মিডলওয়্যার। একটি রিকোয়েস্টকে কেন্দ্রে পৌঁছানোর জন্য প্রতিটি বাইরের স্তর ভেদ করে যেতে হয় এবং রেসপন্সটি একই স্তরগুলির মধ্য দিয়ে বাইরে ফিরে আসে। প্রতিটি স্তর ভিতরে যাওয়ার সময় রিকোয়েস্ট এবং বাইরে যাওয়ার সময় রেসপন্সকে পরিদর্শন ও পরিবর্তন করতে পারে।
মূলত, মিডলওয়্যার হলো একটি ফাংশন বা ক্লাস যা রিকোয়েস্ট অবজেক্ট, রেসপন্স অবজেক্ট এবং অ্যাপ্লিকেশনের রিকোয়েস্ট-রেসপন্স চক্রের পরবর্তী মিডলওয়্যারে অ্যাক্সেস পায়। এর প্রধান উদ্দেশ্যগুলির মধ্যে রয়েছে:
- কোড চালানো: প্রতিটি ইনকামিং রিকোয়েস্টের জন্য কাজ সম্পাদন করা, যেমন লগিং বা পারফরম্যান্স পর্যবেক্ষণ।
- রিকোয়েস্ট এবং রেসপন্স পরিবর্তন করা: হেডার যোগ করা, রেসপন্স বডি সংকুচিত করা, বা ডেটা ফরম্যাট রূপান্তর করা।
- চক্রটিকে শর্ট-সার্কিট করা: রিকোয়েস্ট-রেসপন্স চক্রটি দ্রুত শেষ করা। উদাহরণস্বরূপ, একটি প্রমাণীকরণ মিডলওয়্যার একটি অপ্রমাণিত রিকোয়েস্টকে উদ্দিষ্ট এন্ডপয়েন্টে পৌঁছানোর আগেই ব্লক করতে পারে।
- গ্লোবাল বিষয়গুলি পরিচালনা করা: একটি কেন্দ্রীভূত জায়গায় ত্রুটি হ্যান্ডলিং, CORS (ক্রস-অরিজিন রিসোর্স শেয়ারিং), এবং সেশন ম্যানেজমেন্টের মতো ক্রস-কাটিং বিষয়গুলি পরিচালনা করা।
FastAPI স্টারলেট টুলকিটের উপর নির্মিত, যা ASGI (অ্যাসিঙ্ক্রোনাস সার্ভার গেটওয়ে ইন্টারফেস) স্ট্যান্ডার্ডের একটি শক্তিশালী বাস্তবায়ন প্রদান করে। মিডলওয়্যার ASGI-এর একটি মৌলিক ধারণা, যা এটিকে FastAPI ইকোসিস্টেমে একটি প্রথম-শ্রেণীর নাগরিকে পরিণত করেছে।
সবচেয়ে সহজ ফর্ম: ডেকোরেটর সহ FastAPI মিডলওয়্যার
FastAPI @app.middleware("http") ডেকোরেটর ব্যবহার করে মিডলওয়্যার যোগ করার একটি সহজ উপায় প্রদান করে। এটি সহজ, স্বয়ংসম্পূর্ণ লজিকের জন্য উপযুক্ত যা প্রতিটি HTTP রিকোয়েস্টের জন্য চালানো প্রয়োজন।
আসুন একটি ক্লাসিক উদাহরণ তৈরি করি: প্রতিটি রিকোয়েস্টের জন্য প্রসেসিং সময় গণনা করতে এবং এটি রেসপন্স হেডারে যোগ করার জন্য একটি মিডলওয়্যার। এটি পারফরম্যান্স পর্যবেক্ষণের জন্য অবিশ্বাস্যভাবে দরকারী।
উদাহরণ: একটি প্রসেস-টাইম মিডলওয়্যার
প্রথমে, নিশ্চিত করুন যে আপনার FastAPI এবং Uvicorn-এর মতো একটি ASGI সার্ভার ইনস্টল করা আছে:
pip install fastapi uvicorn
এখন, আসুন main.py নামের একটি ফাইলে কোডটি লিখি:
import time
from fastapi import FastAPI, Request
app = FastAPI()
# মিডলওয়্যার ফাংশনটি সংজ্ঞায়িত করুন
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
# যখন রিকোয়েস্ট আসে তখন শুরুর সময় রেকর্ড করুন
start_time = time.time()
# পরবর্তী মিডলওয়্যার বা এন্ডপয়েন্টে এগিয়ে যান
response = await call_next(request)
# প্রসেসিং সময় গণনা করুন
process_time = time.time() - start_time
# রেসপন্সে কাস্টম হেডার যোগ করুন
response.headers["X-Process-Time"] = str(process_time)
return response
@app.get("/")
async def root():
# কিছু কাজের সিমুলেশন করুন
time.sleep(0.5)
return {"message": "Hello, World!"}
এই অ্যাপ্লিকেশনটি চালানোর জন্য, কমান্ডটি ব্যবহার করুন:
uvicorn main:app --reload
এখন, আপনি যদি cURL-এর মতো একটি টুল বা Postman-এর মতো একটি API ক্লায়েন্ট ব্যবহার করে http://127.0.0.1:8000-এ একটি রিকোয়েস্ট পাঠান, আপনি রেসপন্সে একটি নতুন হেডার দেখতে পাবেন, X-Process-Time, যার মান প্রায় ০.৫ সেকেন্ড হবে।
কোডটি বিশ্লেষণ:
@app.middleware("http"): এই ডেকোরেটরটি আমাদের ফাংশনকে একটি HTTP মিডলওয়্যার হিসাবে রেজিস্টার করে।async def add_process_time_header(request: Request, call_next):: মিডলওয়্যার ফাংশনটি অবশ্যই অ্যাসিঙ্ক্রোনাস হতে হবে। এটি ইনকামিংRequestঅবজেক্ট এবংcall_nextনামের একটি বিশেষ ফাংশন গ্রহণ করে।response = await call_next(request): এটি সবচেয়ে গুরুত্বপূর্ণ লাইন।call_nextরিকোয়েস্টটিকে পাইপলাইনের পরবর্তী ধাপে (অন্য একটি মিডলওয়্যার বা আসল পাথ অপারেশন) পাস করে। আপনাকে অবশ্যই `await` করতে হবে এই কলটি। এর ফলাফল হলো এন্ডপয়েন্ট দ্বারা তৈরিResponseঅবজেক্ট।response.headers[...] = ...: এন্ডপয়েন্ট থেকে রেসপন্স পাওয়ার পর, আমরা এটিকে পরিবর্তন করতে পারি, এক্ষেত্রে একটি কাস্টম হেডার যোগ করে।return response: অবশেষে, পরিবর্তিত রেসপন্সটি ক্লায়েন্টের কাছে পাঠানোর জন্য রিটার্ন করা হয়।
ক্লাস ব্যবহার করে নিজস্ব কাস্টম মিডলওয়্যার তৈরি করা
যদিও ডেকোরেটর পদ্ধতিটি সহজ, এটি আরও জটিল পরিস্থিতির জন্য সীমাবদ্ধ হয়ে যেতে পারে, বিশেষ করে যখন আপনার মিডলওয়্যারের জন্য কনফিগারেশন প্রয়োজন হয় বা কিছু অভ্যন্তরীণ স্টেট পরিচালনা করতে হয়। এই ক্ষেত্রে, FastAPI (স্টারলেটের মাধ্যমে) BaseHTTPMiddleware ব্যবহার করে ক্লাস-ভিত্তিক মিডলওয়্যার সমর্থন করে।
একটি ক্লাস-ভিত্তিক পদ্ধতি আরও ভালো কাঠামো প্রদান করে, এর কনস্ট্রাক্টরে ডিপেন্ডেন্সি ইনজেকশনের অনুমতি দেয় এবং সাধারণত জটিল লজিকের জন্য এটি আরও রক্ষণাবেক্ষণযোগ্য। মূল লজিকটি একটি অ্যাসিঙ্ক্রোনাস dispatch পদ্ধতিতে থাকে।
উদাহরণ: একটি ক্লাস-ভিত্তিক API কী প্রমাণীকরণ মিডলওয়্যার
আসুন একটি আরও ব্যবহারিক মিডলওয়্যার তৈরি করি যা আমাদের API সুরক্ষিত করবে। এটি X-API-Key নামের একটি নির্দিষ্ট হেডারের জন্য পরীক্ষা করবে, এবং যদি কীটি উপস্থিত না থাকে বা অবৈধ হয়, তবে এটি অবিলম্বে একটি 403 Forbidden ত্রুটি প্রতিক্রিয়া ফিরিয়ে দেবে। এটি রিকোয়েস্টকে "শর্ট-সার্কিট" করার একটি উদাহরণ।
main.py ফাইলে:
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
from starlette.responses import Response
# বৈধ API কীগুলির একটি তালিকা। একটি বাস্তব অ্যাপ্লিকেশনে, এটি একটি ডেটাবেস বা একটি সুরক্ষিত ভল্ট থেকে আসবে।
VALID_API_KEYS = ["my-super-secret-key", "another-valid-key"]
class APIKeyMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response:
api_key = request.headers.get("X-API-Key")
if api_key not in VALID_API_KEYS:
# রিকোয়েস্টটিকে শর্ট-সার্কিট করুন এবং একটি ত্রুটি প্রতিক্রিয়া ফিরিয়ে দিন
return JSONResponse(
status_code=403,
content={"detail": "Forbidden: Invalid or missing API Key"}
)
# যদি কীটি বৈধ হয়, রিকোয়েস্টটি নিয়ে এগিয়ে যান
response = await call_next(request)
return response
app = FastAPI()
# অ্যাপ্লিকেশনটিতে মিডলওয়্যার যোগ করুন
app.add_middleware(APIKeyMiddleware)
@app.get("/")
async def root():
return {"message": "Welcome to the secure zone!"}
এখন, যখন আপনি এই অ্যাপ্লিকেশনটি চালাবেন:
X-API-Keyহেডার ছাড়া একটি রিকোয়েস্ট (বা ভুল মান সহ) একটি 403 স্ট্যাটাস কোড এবং JSON ত্রুটি বার্তা পাবে।X-API-Key: my-super-secret-keyহেডার সহ একটি রিকোয়েস্ট সফল হবে এবং 200 OK প্রতিক্রিয়া পাবে।
এই প্যাটার্নটি অত্যন্ত শক্তিশালী। /-এ থাকা এন্ডপয়েন্ট কোডকে API কী যাচাইকরণ সম্পর্কে কিছুই জানতে হবে না; সেই চিন্তাটি সম্পূর্ণরূপে মিডলওয়্যার স্তরে পৃথক করা হয়েছে।
মিডলওয়্যারের সাধারণ এবং শক্তিশালী ব্যবহার
মিডলওয়্যার ক্রস-কাটিং বিষয়গুলি পরিচালনা করার জন্য একটি নিখুঁত টুল। আসুন কিছু সবচেয়ে সাধারণ এবং প্রভাবশালী ব্যবহারের ক্ষেত্রগুলি অন্বেষণ করি।
১. কেন্দ্রীভূত লগিং
প্রোডাকশন অ্যাপ্লিকেশনগুলির জন্য ব্যাপক লগিং অপরিহার্য। মিডলওয়্যার আপনাকে একটি একক পয়েন্ট তৈরি করার অনুমতি দেয় যেখানে আপনি প্রতিটি রিকোয়েস্ট এবং তার সংশ্লিষ্ট রেসপন্স সম্পর্কে গুরুত্বপূর্ণ তথ্য লগ করতে পারেন।
লগিং মিডলওয়্যারের উদাহরণ:
import logging
from fastapi import FastAPI, Request
import time
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
app = FastAPI()
@app.middleware("http")
async def logging_middleware(request: Request, call_next):
start_time = time.time()
# রিকোয়েস্টের বিবরণ লগ করুন
logger.info(f"Incoming request: {request.method} {request.url.path}")
response = await call_next(request)
process_time = time.time() - start_time
# রেসপন্সের বিবরণ লগ করুন
logger.info(f"Response status: {response.status_code} | Process time: {process_time:.4f}s")
return response
এই মিডলওয়্যারটি আসার পথে রিকোয়েস্টের মেথড এবং পাথ লগ করে, এবং যাওয়ার পথে রেসপন্সের স্ট্যাটাস কোড এবং মোট প্রসেসিং সময় লগ করে। এটি আপনার অ্যাপ্লিকেশনের ট্র্যাফিকের উপর অমূল্য দৃশ্যমানতা প্রদান করে।
২. গ্লোবাল এরর হ্যান্ডলিং
ডিফল্টরূপে, আপনার কোডে একটি আনহ্যান্ডেলড ব্যতিক্রমের ফলে 500 ইন্টারনাল সার্ভার এরর হবে, যা ক্লায়েন্টের কাছে স্ট্যাক ট্রেস এবং বাস্তবায়নের বিবরণ প্রকাশ করতে পারে। একটি গ্লোবাল এরর হ্যান্ডলিং মিডলওয়্যার সমস্ত ব্যতিক্রম ধরতে পারে, সেগুলিকে অভ্যন্তরীণ পর্যালোচনার জন্য লগ করতে পারে, এবং একটি প্রমিত, ব্যবহারকারী-বান্ধব ত্রুটি প্রতিক্রিয়া ফিরিয়ে দিতে পারে।
এরর হ্যান্ডলিং মিডলওয়্যারের উদাহরণ:
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
import logging
logger = logging.getLogger(__name__)
app = FastAPI()
@app.middleware("http")
async def error_handling_middleware(request: Request, call_next):
try:
return await call_next(request)
except Exception as e:
logger.error(f"An unhandled error occurred: {e}", exc_info=True)
return JSONResponse(
status_code=500,
content={"detail": "An internal server error occurred. Please try again later."}
)
@app.get("/error")
async def cause_error():
return 1 / 0 # এটি একটি ZeroDivisionError তৈরি করবে
এই মিডলওয়্যারটি থাকায়, /error-এ একটি রিকোয়েস্ট আর সার্ভার ক্র্যাশ করবে না বা স্ট্যাক ট্রেস প্রকাশ করবে না। পরিবর্তে, এটি একটি পরিষ্কার JSON বডি সহ একটি 500 স্ট্যাটাস কোড সুন্দরভাবে ফিরিয়ে দেবে, যখন ডেভেলপারদের তদন্তের জন্য সম্পূর্ণ ত্রুটিটি সার্ভার-সাইডে লগ করা হবে।
৩. CORS (ক্রস-অরিজিন রিসোর্স শেয়ারিং)
যদি আপনার ফ্রন্টএন্ড অ্যাপ্লিকেশনটি আপনার FastAPI ব্যাকএন্ডের থেকে ভিন্ন ডোমেইন, প্রোটোকল বা পোর্ট থেকে পরিবেশন করা হয়, তবে ব্রাউজারগুলি সেম-অরিজিন পলিসির কারণে রিকোয়েস্টগুলি ব্লক করবে। CORS হলো এই নীতিটি শিথিল করার প্রক্রিয়া। FastAPI এই নির্দিষ্ট উদ্দেশ্যে একটি বিশেষ, অত্যন্ত কনফিগারযোগ্য `CORSMiddleware` প্রদান করে।
CORS কনফিগারেশনের উদাহরণ:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# অনুমোদিত অরিজিনগুলির তালিকা নির্ধারণ করুন। পাবলিক API-এর জন্য "*" ব্যবহার করুন, তবে আরও ভালো নিরাপত্তার জন্য নির্দিষ্ট হোন।
origins = [
"http://localhost:3000",
"https://my-production-frontend.com",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True, # ক্রস-অরিজিন রিকোয়েস্টে কুকি অন্তর্ভুক্ত করার অনুমতি দিন
allow_methods=["*"], # সমস্ত স্ট্যান্ডার্ড HTTP মেথড অনুমোদন করুন
allow_headers=["*"], # সমস্ত হেডার অনুমোদন করুন
)
এটি এমন একটি প্রথম মিডলওয়্যার যা আপনি সম্ভবত একটি ডিকাপলড ফ্রন্টএন্ড সহ যেকোনো প্রকল্পে যোগ করবেন, যা একটি একক, কেন্দ্রীয় অবস্থান থেকে ক্রস-অরিজিন নীতিগুলি পরিচালনা করা সহজ করে তোলে।
৪. GZip কম্প্রেশন
HTTP রেসপন্স সংকুচিত করা তাদের আকার উল্লেখযোগ্যভাবে কমাতে পারে, যা ক্লায়েন্টদের জন্য দ্রুত লোড সময় এবং কম ব্যান্ডউইথ খরচের দিকে পরিচালিত করে। FastAPI এটি স্বয়ংক্রিয়ভাবে পরিচালনা করার জন্য একটি `GZipMiddleware` অন্তর্ভুক্ত করে।
GZip মিডলওয়্যারের উদাহরণ:
from fastapi import FastAPI
from fastapi.middleware.gzip import GZipMiddleware
app = FastAPI()
# GZip মিডলওয়্যার যোগ করুন। আপনি কম্প্রেশনের জন্য একটি ন্যূনতম আকার সেট করতে পারেন।
app.add_middleware(GZipMiddleware, minimum_size=1000)
@app.get("/")
async def root():
# এই রেসপন্সটি ছোট এবং এটি জিজিপ করা হবে না।
return {"message": "Hello World"}
@app.get("/large-data")
async def large_data():
# এই বড় রেসপন্সটি মিডলওয়্যার দ্বারা স্বয়ংক্রিয়ভাবে জিজিপ করা হবে।
return {"data": "a_very_long_string..." * 1000}
এই মিডলওয়্যারের সাথে, ১০০০ বাইটের চেয়ে বড় যেকোনো রেসপন্স সংকুচিত হবে যদি ক্লায়েন্ট নির্দেশ করে যে সে GZip এনকোডিং গ্রহণ করে (যা প্রায় সমস্ত আধুনিক ব্রাউজার এবং ক্লায়েন্ট করে থাকে)।
উন্নত ধারণা এবং সেরা অনুশীলন
মিডলওয়্যারে আপনি যত বেশি পারদর্শী হবেন, পরিষ্কার, দক্ষ এবং অনুমানযোগ্য কোড লেখার জন্য কিছু সূক্ষ্মতা এবং সেরা অনুশীলন বোঝা গুরুত্বপূর্ণ।
১. মিডলওয়্যারের ক্রম গুরুত্বপূর্ণ!
এটি মনে রাখার সবচেয়ে গুরুত্বপূর্ণ নিয়ম। মিডলওয়্যার অ্যাপ্লিকেশনটিতে যে ক্রমে যোগ করা হয় সেই ক্রমে প্রক্রিয়া করা হয়। প্রথমে যোগ করা মিডলওয়্যারটি হলো "পেঁয়াজের" সবচেয়ে বাইরের স্তর।
এই সেটআপটি বিবেচনা করুন:
app.add_middleware(ErrorHandlingMiddleware) # সবচেয়ে বাইরের
app.add_middleware(LoggingMiddleware)
app.add_middleware(AuthenticationMiddleware) # সবচেয়ে ভিতরের
একটি রিকোয়েস্টের প্রবাহ হবে:
ErrorHandlingMiddlewareরিকোয়েস্টটি গ্রহণ করে। এটি তার `call_next` কে একটি `try...except` ব্লকে আবৃত করে।- এটি `next` কল করে, রিকোয়েস্টটি `LoggingMiddleware`-এ পাস করে।
LoggingMiddlewareরিকোয়েস্টটি গ্রহণ করে, এটি লগ করে এবং `next` কল করে।AuthenticationMiddlewareরিকোয়েস্টটি গ্রহণ করে, ক্রেডেনশিয়াল যাচাই করে এবং `next` কল করে।- রিকোয়েস্টটি অবশেষে এন্ডপয়েন্টে পৌঁছায়।
- এন্ডপয়েন্টটি একটি রেসপন্স ফিরিয়ে দেয়।
AuthenticationMiddlewareরেসপন্সটি গ্রহণ করে এবং এটি উপরে পাস করে।LoggingMiddlewareরেসপন্সটি গ্রহণ করে, এটি লগ করে এবং এটি উপরে পাস করে।ErrorHandlingMiddlewareচূড়ান্ত রেসপন্সটি গ্রহণ করে এবং এটি ক্লায়েন্টের কাছে ফিরিয়ে দেয়।
এই ক্রমটি যৌক্তিক: এরর হ্যান্ডলারটি বাইরে থাকে যাতে এটি পরবর্তী যেকোনো স্তর থেকে, অন্যান্য মিডলওয়্যার সহ, ত্রুটি ধরতে পারে। প্রমাণীকরণ স্তরটি গভীরে থাকে, তাই আমরা এমন রিকোয়েস্ট লগিং বা প্রসেসিং নিয়ে মাথা ঘামাই না যা যাইহোক প্রত্যাখ্যান করা হবে।
২. `request.state` ব্যবহার করে ডেটা পাস করা
কখনও কখনও, একটি মিডলওয়্যারকে এন্ডপয়েন্টে তথ্য পাস করতে হয়। উদাহরণস্বরূপ, একটি প্রমাণীকরণ মিডলওয়্যার একটি JWT ডিকোড করে ব্যবহারকারীর আইডি বের করতে পারে। এটি কীভাবে এই ব্যবহারকারী আইডি পাথ অপারেশন ফাংশনের জন্য উপলব্ধ করতে পারে?
ভুল উপায় হলো রিকোয়েস্ট অবজেক্টকে সরাসরি পরিবর্তন করা। সঠিক উপায় হলো `request.state` অবজেক্ট ব্যবহার করা। এটি এই নির্দিষ্ট উদ্দেশ্যে সরবরাহ করা একটি সহজ, খালি অবজেক্ট।
উদাহরণ: মিডলওয়্যার থেকে ব্যবহারকারীর ডেটা পাস করা
# আপনার প্রমাণীকরণ মিডলওয়্যারের dispatch পদ্ধতিতে:
# ... টোকেন যাচাই এবং ব্যবহারকারীকে ডিকোড করার পরে ...
user_data = {"id": 123, "username": "global_dev"}
request.state.user = user_data
response = await call_next(request)
# আপনার এন্ডপয়েন্টে:
@app.get("/profile")
async def get_user_profile(request: Request):
current_user = request.state.user
return {"profile_for": current_user}
এটি লজিককে পরিষ্কার রাখে এবং `Request` অবজেক্টের নেমস্পেসকে দূষিত করা থেকে বিরত রাখে।
৩. পারফরম্যান্স বিবেচনা
যদিও মিডলওয়্যার শক্তিশালী, প্রতিটি স্তর অল্প পরিমাণে ওভারহেড যোগ করে। উচ্চ-পারফরম্যান্স অ্যাপ্লিকেশনগুলির জন্য, এই বিষয়গুলি মনে রাখবেন:
- এটিকে হালকা রাখুন: মিডলওয়্যার লজিক যতটা সম্ভব দ্রুত এবং দক্ষ হওয়া উচিত।
- অ্যাসিঙ্ক্রোনাস হোন: যদি আপনার মিডলওয়্যারকে I/O অপারেশন করতে হয় (যেমন একটি ডেটাবেস চেক), নিশ্চিত করুন যে এটি সম্পূর্ণরূপে `async` যাতে সার্ভারের ইভেন্ট লুপ ব্লক না হয়।
- উদ্দেশ্য নিয়ে ব্যবহার করুন: আপনার প্রয়োজন নেই এমন মিডলওয়্যার যোগ করবেন না। প্রতিটি কল স্ট্যাকের গভীরতা এবং প্রক্রিয়াকরণের সময় বাড়ায়।
৪. আপনার মিডলওয়্যার টেস্টিং
মিডলওয়্যার আপনার অ্যাপ্লিকেশনের লজিকের একটি গুরুত্বপূর্ণ অংশ এবং এটি পুঙ্খানুপুঙ্খভাবে পরীক্ষা করা উচিত। FastAPI-এর `TestClient` এটি সহজ করে তোলে। আপনি প্রয়োজনীয় শর্তাবলী সহ এবং ছাড়া (যেমন, বৈধ API কী সহ এবং ছাড়া) রিকোয়েস্ট পাঠিয়ে পরীক্ষা লিখতে পারেন এবং নিশ্চিত করতে পারেন যে মিডলওয়্যারটি প্রত্যাশিতভাবে আচরণ করছে।
APIKeyMiddleware-এর জন্য উদাহরণ টেস্ট:
from fastapi.testclient import TestClient
from .main import app # আপনার FastAPI অ্যাপ ইম্পোর্ট করুন
client = TestClient(app)
def test_request_without_api_key_is_forbidden():
response = client.get("/")
assert response.status_code == 403
assert response.json() == {"detail": "Forbidden: Invalid or missing API Key"}
def test_request_with_valid_api_key_is_successful():
headers = {"X-API-Key": "my-super-secret-key"}
response = client.get("/", headers=headers)
assert response.status_code == 200
assert response.json() == {"message": "Welcome to the secure zone!"}
উপসংহার
FastAPI মিডলওয়্যার আধুনিক ওয়েব API তৈরি করা যেকোনো ডেভেলপারের জন্য একটি মৌলিক এবং শক্তিশালী টুল। এটি ক্রস-কাটিং বিষয়গুলি পরিচালনা করার একটি মার্জিত এবং পুনঃব্যবহারযোগ্য উপায় প্রদান করে, যা সেগুলিকে আপনার মূল বিজনেস লজিক থেকে পৃথক করে। প্রতিটি রিকোয়েস্ট এবং রেসপন্সকে বাধা দিয়ে এবং প্রক্রিয়া করে, মিডলওয়্যার আপনাকে শক্তিশালী লগিং, কেন্দ্রীভূত এরর হ্যান্ডলিং, কঠোর নিরাপত্তা নীতি এবং কম্প্রেশনের মতো পারফরম্যান্স উন্নতি বাস্তবায়ন করতে দেয়।
`@app.middleware("http")` ডেকোরেটরের মতো সহজ পদ্ধতি থেকে শুরু করে অত্যাধুনিক, ক্লাস-ভিত্তিক সমাধান পর্যন্ত, আপনার প্রয়োজন অনুযায়ী সঠিক পদ্ধতি বেছে নেওয়ার নমনীয়তা রয়েছে। মূল ধারণা, সাধারণ ব্যবহারের ক্ষেত্র এবং মিডলওয়্যার ক্রম ও স্টেট ম্যানেজমেন্টের মতো সেরা অনুশীলনগুলি বোঝার মাধ্যমে, আপনি আরও পরিষ্কার, নিরাপদ এবং অত্যন্ত রক্ষণাবেক্ষণযোগ্য FastAPI অ্যাপ্লিকেশন তৈরি করতে পারবেন।
এখন আপনার পালা। আপনার পরবর্তী FastAPI প্রকল্পে কাস্টম মিডলওয়্যার একীভূত করা শুরু করুন এবং আপনার API ডিজাইনে একটি নতুন স্তরের নিয়ন্ত্রণ এবং সৌন্দর্য আনলক করুন। সম্ভাবনাগুলি বিশাল, এবং এই বৈশিষ্ট্যটি আয়ত্ত করা নিঃসন্দেহে আপনাকে আরও কার্যকর এবং দক্ষ ডেভেলপার করে তুলবে।